package Chess;

import java.awt.Color;

/**
 *	A class representing a Square on a chess Board.
 *
 *	@author		Jeff Chan, Ricky Saini
 */
public class Square{
	
	char file, rank;
	
	/**
	 *	Class constructor specifying the file and rank of the Square.
	 *
	 *	@param	f	the file of the Square
	 *	@param	r	the rank of the Square
	 */
	public Square(char f, char r) {
		file = f;
		rank = r;
	}
	
	/**
	 *	Class constructor specifying the file-rank notation of the Square.
	 *	For instance, <pre>f6</pre>
	 *	
	 *	@param	co	the file-rank notation of the Square
	 */
	public Square(String co) {		
		file = co.charAt(0);
		rank = co.charAt(1);
	}
	
	/**
	 *	Returns the file of the Square
	 *	
	 *	@return	the file
	 */
	public char getFile() {
		return file;
	}    
	
	/**
	 *	Returns the rank of the Square
	 *
	 *	@return	the rank
	 */
	public char getRank() {
		return rank;
	}
	
	/**
	 *	Returns the distance between the rank of this
	 *	Square and the rank of the specified Square.
	 *	
	 *	@param	other	the specified Square
	 *	@return			the distance between ranks
	 */
	public int distanceBetweenRank(Square other) {
		return getRank() - other.getRank();
	}
	
	/**
	 *	Returns the distance between the file of this
	 *	Square and the file of the specified Square.
	 *	
	 *	@param	other	the specified Square
	 *	@return			the distance between files
	 */
	public int distanceBetweenFile(Square other) {
		return getFile() - other.getFile();
	}

	/**
	 *	Returns true if this Square is in the same rank
	 *	as the specified Square. Set to false if not.
	 *	
	 *	@param	other	the specified Square
	 *	@return			true if this Square is in the same rank as the specified Square
	 */
	public boolean isInSameRank(Square other) {
		return distanceBetweenRank(other) == 0;
	}
	
	/**
	 *	Returns true if this Square is in the same file
	 *	as the specified Square. Set to false if not.
	 *	
	 *	@param	other	the specified Square
	 *	@return			true if this Square is in the same file as the specified Square
	 */
	public boolean isInSameFile(Square other) {
		return distanceBetweenFile(other) == 0;
	}
	
	/**
	 *	Returns true if this Square is diagonal to
	 *	the specified Square. Set to false if not.
	 *	
	 *	@param	other	the specified Square
	 *	@return			true if this Square is diagonal to the specified Square
	 */
	public boolean isDiagonal(Square other) {
		return Math.abs(distanceBetweenFile(other)) == Math.abs(distanceBetweenRank(other));
	}
	
	/**
	 *	Returns true if this Square is adjacent to
	 *	the specified Square. Set to false if not.
	 *	
	 *	@param	other	the specified Square
	 *	@return			true if this Square is adjacent to the specified Square
	 */
	public boolean isAdjacent(Square other) {
		return isAdjacentHorizontally(other) || isAdjacentVertically(other) || isAdjacentDiagonally(other);
	}
	
	/**
	 *	Returns true if this Square is in the last row
	 *	for the specified Color. Set to false if not.
	 *	Returns true if Color is white and rank is 8 or
	 *	if Color is black and rank is 1.
	 *	
	 *	@param	other	the specified Square
	 *	@return			true if this Square is in the last row for the specified Color
	 */
	public boolean isInLastRow(Color color) {
		if ((color.equals(Color.WHITE) && getRank() == '8') || (color.equals(Color.BLACK) && getRank() == '1')) {
			return true;
		}
		return false;
	}
	
	/**
	 *	Returns true if this Square is adjacent horizontally
	 *	to the specified Square. Set to false otherwise.
	 *
	 *	@param	other	the specified Square
	 *	@return			true if this Square is adjacent horizontally to the specified Square
	 */
	public boolean isAdjacentHorizontally(Square other) {
		int fileDist = Math.abs(distanceBetweenFile(other));
		int rankDist = Math.abs(distanceBetweenRank(other));
		return fileDist == 1 && rankDist == 0;
	}
	
	/**
	 *	Returns true if this Square is adjacent vertically
	 *	to the specified Square. Set to false otherwise.
	 *
	 *	@param	other	the specified Square
	 *	@return			true if this Square is adjacent vertically to the specified Square
	 */
	public boolean isAdjacentVertically(Square other) {
		int fileDist = Math.abs(distanceBetweenFile(other));
		int rankDist = Math.abs(distanceBetweenRank(other));
		return fileDist == 0 && rankDist == 1;
	}

	/**
	 *	Returns true if this Square is adjacent diagonally
	 *	to the specified Square. Set to false otherwise.
	 *
	 *	@param	other	the specified Square
	 *	@return			true if this Square is adjacent diagonally to the specified Square
	 */
	public boolean isAdjacentDiagonally(Square other) {
		int fileDist = Math.abs(distanceBetweenFile(other));
		int rankDist = Math.abs(distanceBetweenRank(other));
		return fileDist == 1 && rankDist == 1;
	}
	
	/**
	 *	Compares this Square to the object. The result is true
	 *	if and only if the argument is not null and is a Square
	 *	object that represents the same file and rank as this
	 *	object.
	 *
	 *	@param	anObject	the object to compare this Square against
	 *	@return			true if the Square are equal; false otherwise.
	 */
	public boolean equals(Object anObject) {
		if (anObject == null || !(anObject instanceof Square)) {
			return false;
		}
		
		Square that = (Square)anObject;
		if (this.toString().equals(that.toString())) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 *	Returns a String object representing this Square's value.
	 *	The value is converted to file-rank representation and
	 *	returned as a string.
	 *	
	 *	@return	a string representation of the file-rank of this Square
	 */
	public String toString() {
		return new String("" + file + rank);
	}
	
	/**
	 *	Returns a hash code value for the Square based on the file-rank.
	 *	
	 *	@return	a hash code value of this Square
	 */
    public int hashCode() {
		return this.toString().hashCode();
    }
}